#include "utils/file/file_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include <string.h>  // 包含这个头文件来使用 strlen 函数
#include "cJSON.h"  // 添加 cJSON 头文件

#define FILE_UTILS_TAG "FILE_UTILS"
//初始化状态
static bool spiffs_initialized = false;
// 检查 SPIFFS 文件系统是否已挂载
bool spiffs_is_mounted() {
    esp_vfs_spiffs_conf_t conf = {
            .base_path = "/spiffs",
            .partition_label = "spiffs",
            .max_files = 5,
            .format_if_mount_failed = false
    };

    esp_err_t ret = esp_spiffs_info(conf.partition_label, NULL, NULL);
    return ret == ESP_OK;
}
esp_err_t format_spiffs() {
    ESP_LOGW(FILE_UTILS_TAG, "Formatting SPIFFS partition...");
    esp_err_t ret = esp_spiffs_format("spiffs");
    if (ret != ESP_OK) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to format SPIFFS: %s", esp_err_to_name(ret));
        return ret;
    }
    return ESP_OK;
}
// 初始化 SPIFFS 文件系统
esp_err_t spiffs_init() {
    if(spiffs_initialized){
        return ESP_OK;
    }

    esp_vfs_spiffs_conf_t conf = {
            .base_path = "/spiffs",
            .partition_label = "spiffs",
            .max_files = 5,
            .format_if_mount_failed = false // 关键修改
    };

    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    if (ret != ESP_OK) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to mount SPIFFS (%s)", esp_err_to_name(ret));

        // 提供更多错误信息
        if (ret == ESP_FAIL) {
            ESP_LOGE(FILE_UTILS_TAG, "SPIFFS partition may be corrupted. Consider formatting manually.");
        } else if (ret == ESP_ERR_NOT_FOUND) {
            ESP_LOGE(FILE_UTILS_TAG, "SPIFFS partition not found in partition table.");
        }

        return ret;
    }

    // 验证挂载结果
    size_t total = 0, used = 0;
    ret = esp_spiffs_info(conf.partition_label, &total, &used);
    if (ret != ESP_OK) {
        ESP_LOGE(FILE_UTILS_TAG, "SPIFFS info check failed (%s)", esp_err_to_name(ret));
        esp_vfs_spiffs_unregister(conf.partition_label);
        return ret;
    }

    ESP_LOGI(FILE_UTILS_TAG, "SPIFFS mounted. Size: %u/%u bytes", (unsigned int)used, (unsigned int)total);
    spiffs_initialized = true;
    return ESP_OK;
}
// 确保SPIFFS已初始化的辅助函数
esp_err_t ensure_spiffs_fmt_initialized() {
    if (!spiffs_initialized) {
        esp_err_t ret = spiffs_init();
        if (ret != ESP_OK) {
            ESP_LOGE(FILE_UTILS_TAG, "SPIFFS initialization failed before operation.");
        }
        return ret;
    }
    return ESP_OK;
}
bool file_exists(const char* path) {
    FILE* file = fopen(path, "r");
    if (file) {
        fclose(file);
        return true;
    }
    return false;
}

char* read_file_content(const char* path) {
    // 检查路径是否为空指针
    if (path == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "File path is NULL");
        return NULL;
    }

    esp_err_t ret = ensure_spiffs_fmt_initialized();
    if (ret != ESP_OK) {
        return NULL;
    }

    FILE* file = fopen(path, "r");
    if (file == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to open file: %s", path);
        return NULL;
    }

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long size = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 分配内存
    char* buffer = (char*)malloc(size + 1);
    if (buffer == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to allocate memory for file content");
        fclose(file);
        return NULL;
    }

    // 读取文件内容
    size_t bytes_read = fread(buffer, 1, size, file);
    if (bytes_read < (size_t)size) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to read the entire file: %s. Expected %ld bytes, read %zu bytes.", path, size, bytes_read);
        free(buffer);
        fclose(file);
        return NULL;
    }

    // 添加字符串结束符
    buffer[bytes_read] = '\0';

    // 关闭文件
    fclose(file);
    return buffer;
}

// 将字符串存储到文件的方法
esp_err_t write_string_to_file(const char *str, const char *path) {
    esp_err_t ret = ensure_spiffs_fmt_initialized();
    if (ret != ESP_OK) {
        return ret;
    }

    FILE *file = fopen(path, "w");
    if (file == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to open file for writing: %s", path);
        return ESP_FAIL;
    }

    size_t len = strlen(str);
    size_t bytes_written = fwrite(str, 1, len, file);
    if (bytes_written != len) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to write all data to file: %s. Error: %d", path, ferror(file));
        fclose(file);
        return ESP_FAIL;
    }

    fclose(file);
    ESP_LOGI(FILE_UTILS_TAG, "Successfully wrote string to file: %s", path);
    return ESP_OK;
}

// 读取JSON文件的函数
char* read_json_file(const char* filename) {
    esp_err_t ret = ensure_spiffs_fmt_initialized();
    if (ret != ESP_OK) {
        return NULL;
    }

    FILE* file = fopen(filename, "r");
    if (file == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "无法打开文件");
        return NULL;
    }

    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    char* content = (char*)malloc(file_size + 1);
    if (content == NULL) {
        fclose(file);
        ESP_LOGE(FILE_UTILS_TAG, "内存分配失败");
        return NULL;
    }

    size_t bytes_read = fread(content, 1, file_size, file);
    if (bytes_read < (size_t)file_size) {
        ESP_LOGE(FILE_UTILS_TAG, "Failed to read the entire JSON file: %s. Expected %ld bytes, read %zu bytes.", filename, file_size, bytes_read);
        free(content);
        fclose(file);
        return NULL;
    }

    content[bytes_read] = '\0';
    fclose(file);
    ESP_LOGI(FILE_UTILS_TAG, "读取的文件内容: %s", content); // 添加调试信息
    return content;
}

// 验证并转换为JSON对象
cJSON* validate_and_convert(const char* content) {
    if (content == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "JSON内容为空");
        return NULL;
    }
    cJSON* root = cJSON_Parse(content);
    if (root == NULL) {
        const char* error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            ESP_LOGE(FILE_UTILS_TAG, "JSON解析错误: %s", error_ptr);
        } else {
            ESP_LOGE(FILE_UTILS_TAG, "JSON解析错误，但无法获取错误指针");
        }
        return NULL;
    }
    return root;
}

// 将JSON对象转换为字符串
char* json_object_to_string(cJSON* root) {
    if (root == NULL) {
        ESP_LOGE(FILE_UTILS_TAG, "JSON对象为空");
        return NULL;
    }
    return cJSON_PrintUnformatted(root);
}